
package com.lzx.iteam.contactssearch;

import android.accounts.Account;
import android.content.*;
import android.database.Cursor;
import android.graphics.*;
import android.net.Uri;
import android.os.RemoteException;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.ContactsContract.*;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.text.TextUtils;
import android.util.Log;
import com.lzx.iteam.provider.CloudContactsDB;
import com.lzx.iteam.provider.CloudContactsDB.CommunicationRule;
import com.lzx.iteam.util.*;

import java.util.*;

/**
 * contacts数据库读相关操作
 *
 * @author
 */
public class ContactsDBReader {

    private static ContactsDBReader mInstance;

    public static ContactsDBReader getInstance() {
        if (mInstance == null) {
            mInstance = new ContactsDBReader();
        }
        return mInstance;
    }

    public static void setInstance(ContactsDBReader instance) {
        mInstance = instance;
    }

    public static final int SUMMARY_ID_COLUMN_INDEX = 0;

    public static final int SUMMARY_NAME_COLUMN_INDEX = 1;

    public static final int SUMMARY_STARRED_COLUMN_INDEX = 2;

    public static final int SUMMARY_TIMES_CONTACTED_COLUMN_INDEX = 3;

    public static final int SUMMARY_PHOTO_ID_COLUMN_INDEX = 4;

    public static final int SUMMARY_LOOKUP_KEY = 5;

    public static final int SUMMARY_HAS_PHONE_COLUMN_INDEX = 6;

    public static final int SUMMARY_CONTACT_STATUS_TIMESTAMP = 7;

    public static final String[] CONTACTS_SUMMARY_PROJECTION = new String[]{
            Contacts._ID, // 0
            Contacts.DISPLAY_NAME, // 1
            Contacts.STARRED, // 2
            Contacts.TIMES_CONTACTED, // 3
            // Contacts.CONTACT_PRESENCE, // 4
            Contacts.PHOTO_ID, // 4
            Contacts.LOOKUP_KEY, // 5
            Contacts.HAS_PHONE_NUMBER, // 6
            Contacts.CONTACT_STATUS_TIMESTAMP
    };

    /*private static final String[] RAW_CONTACT_PROJECTION = {
            RawContacts._ID, 
            RawContacts.CUSTOM_RINGTONE,
            RawContacts.STARRED,
            RawContacts.DELETED
    };*/

    public static final String[] DATA_PROJECTION = {
            Data._ID, Data.RAW_CONTACT_ID, Data.CONTACT_ID, Data.MIMETYPE, Data.IS_PRIMARY,
            Data.IS_SUPER_PRIMARY, Data.DATA1, Data.DATA2, Data.DATA3, Data.DATA4, Data.DATA5,
            Data.DATA6, Data.DATA7, Data.DATA8, Data.DATA9, Data.DATA10, Data.DATA11, Data.DATA12,
            Data.DATA13, Data.DATA14, Data.DATA15, Data.DISPLAY_NAME
    };


    private static final String[] DATA_TYPE = new String[]{
            Data.CONTACT_ID, Data.MIMETYPE, Data.DATA1
    };

    private static final String[] CONTACT_ID = new String[]{
            Contacts._ID
    };

    private static final String[] TIME_CONTACTED = new String[]{
            Contacts.TIMES_CONTACTED
    };

    private static final String[] PHOTO_ID = new String[]{
            Contacts.PHOTO_ID
    };

    private static int ifIceCreamAbove = -1;

    public static final class GroupInfo {

        public long mGroupID;

        public String mGroupTitle;

        public String mGroupAccountName;

        public String mGroupAccountType;

        public int mSystemID;

        // 该群组对应的成员数量
        public int mMembersCount;

//        public boolean isSel = false;
    }

    // 根据contactsId得到联系的频率
    public static int getContactedNumber(long contactId, ContentResolver contentResolver) {

        int contactedNumber = 0;
        Cursor cursor = null;
        try {
            cursor = contentResolver.query(Contacts.CONTENT_URI, TIME_CONTACTED,
                    Contacts._ID + " = " + contactId, null, null);

            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    contactedNumber = cursor.getInt(0);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return contactedNumber;
    }

    public static long getPhotoId(long contactId, Context context) {

        // do not change the initial value
        long photoId = 0;
        Cursor cursor = null;
        try {
            cursor = context.getContentResolver().query(Contacts.CONTENT_URI, PHOTO_ID,
                    Contacts._ID + " = " + contactId, null, null);

            if (cursor != null) {
                if (cursor.moveToFirst()) {
                    photoId = cursor.getInt(0);
                }
            }
        } catch (Exception e){
            Log.e("strPhoneNumber**",e.toString());
        }
        finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return photoId;
    }


    public static final String[] PHONE_PROJECTION = {
            Phone.NUMBER, Phone.TYPE
    };

    public static ArrayList<String> getPhoneNumbers(Uri contactUri, Context context) {

        ArrayList<String> phoneNumberList = new ArrayList<String>();
        Uri phoneUri = Uri.withAppendedPath(contactUri,
                Contacts.Data.CONTENT_DIRECTORY);
        Cursor c = context.getContentResolver().query(phoneUri, PHONE_PROJECTION,
                Data.MIMETYPE + "=?", new String[]{
                        Phone.CONTENT_ITEM_TYPE
                }, null);

        c.moveToFirst();

        boolean result = false;
        for (int i = 0; i < c.getCount() && !result; i++) {
            c.moveToPosition(i);
            String phoneNumber = c.getString(0);
            int type = c.getInt(1);
            phoneNumberList.add(phoneNumber);
        }

        c.close();

        return phoneNumberList;

    }

    public static HashSet<Long> getContactIdByPhoneNumber(Context context, String phoneNumber) {
        HashSet<Long> contactIdSet = null;

        Cursor cursor = context.getContentResolver().query(
                Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)),
                new String[]{
                        PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID,
                        PhoneLookup.IN_VISIBLE_GROUP
                }, null, null, null);

        if (cursor != null) {
            try {
                contactIdSet = new HashSet<Long>();
                while (cursor.moveToNext()) {
                    contactIdSet.add(cursor.getLong(0));
                }
            } finally {
                cursor.close();
            }
        }

        return contactIdSet;
    }

    /**
     * 根据号码获得 contactId
     * @param context
     * @param phoneNumber
     * @return
     */
    public static long getOneContactIdByPhoneNum(Context context, String phoneNumber) {
        if (StringUtil.isEmpty(phoneNumber)) {
            return -1;
        }
        Cursor cursor = context.getContentResolver().query(
                Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber)),
                new String[]{
                        PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID,
                        PhoneLookup.IN_VISIBLE_GROUP
                }, null, null, null);

        try {
            if (cursor != null && cursor.moveToNext()) {
                return cursor.getLong(0);
            }
        } finally {
            cursor.close();
        }

        return -1;
    }


    /**
     * 根据号码获得 名字
     * @param context
     * @param phoneNumber
     * @return
     */
    public static String getContactName(Context context, final String phoneNumber) {
        Uri uri;
        String[] projection;
        Uri mBaseUri = android.provider.Contacts.Phones.CONTENT_FILTER_URL;
        projection = new String[]{android.provider.Contacts.People.NAME};
        try {
            Class<?> c = Class.forName("android.provider.ContactsContract$PhoneLookup");
            mBaseUri = (Uri) c.getField("CONTENT_FILTER_URI").get(mBaseUri);
            projection = new String[]{"display_name"};
        } catch (Exception e) {
        }


        uri = Uri.withAppendedPath(mBaseUri, Uri.encode(phoneNumber));
        Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);

        String contactName = "";

        if (cursor.moveToFirst()) {
            contactName = cursor.getString(0);
        }

        cursor.close();
        cursor = null;

        return contactName;
    }


    public static final String SELECTION_FAMILYNAME = Data.MIMETYPE + " = ? and " + StructuredName.FAMILY_NAME + " = ? ";
    public static final String SELECTION_GIVENNAME = Data.MIMETYPE + " = ? and " + StructuredName.GIVEN_NAME + " = ? ";

    public static HashSet<Long> getContactIdByFirstName(Context context, String firstName) {
        HashSet<Long> contactIdSet = null;

        Cursor cursor = context.getContentResolver().query(
                Data.CONTENT_URI,
                new String[]{
                        Data.CONTACT_ID
                }, SELECTION_GIVENNAME, new String[]{StructuredName.CONTENT_ITEM_TYPE, firstName}, null);
        try {
            contactIdSet = new HashSet<Long>();
            while (cursor.moveToNext()) {
                contactIdSet.add(cursor.getLong(0));
            }
        } finally {
            cursor.close();
        }

        return contactIdSet;
    }

    public static HashSet<Long> getContactIdByLastName(Context context, String lastName) {
        HashSet<Long> contactIdSet = null;

        Cursor cursor = context.getContentResolver().query(
                Data.CONTENT_URI,
                new String[]{
                        Data.CONTACT_ID
                }, SELECTION_FAMILYNAME, new String[]{StructuredName.CONTENT_ITEM_TYPE, lastName}, null);
        try {
            contactIdSet = new HashSet<Long>();
            while (cursor.moveToNext()) {
                contactIdSet.add(cursor.getLong(0));
            }
        } finally {
            cursor.close();
        }

        return contactIdSet;
    }

    public static HashSet<Long> getContactIdByEmail(Context context, String email) {
        HashSet<Long> contactIdSet = null;

        Uri uri = Uri.withAppendedPath(Email.CONTENT_LOOKUP_URI, Uri.encode(email));
        Cursor c = context.getContentResolver().query(uri,
                new String[]{Email.CONTACT_ID},
                null, null, null);

        if (c != null) {
            try {
                contactIdSet = new HashSet<Long>();
                while (c.moveToNext()) {
                    contactIdSet.add(c.getLong(0));
                }
            } finally {
                c.close();
            }
        }

        return contactIdSet;
    }

    public static long getContactIdByDisplayName(Context context, String displayName) {
        long contactId = -1;
        Cursor cursor = context.getContentResolver().query(
                Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.decode(displayName)),
                new String[]{
                        PhoneLookup._ID, PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_ID
                }, null, null, null);
        try {
            if (cursor.moveToFirst()) {
                contactId = cursor.getLong(0);
            }
        } finally {
            cursor.close();
        }

        return contactId;
    }


    public static String getContactNameByNum(Context context, String phoneNum) {
        if(phoneNum == null || StringUtil.isEmpty(phoneNum)){
            return "未知";
        }else{
            Cursor cursor = context.getContentResolver().query(
                    Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.decode(phoneNum)),
                    new String[]{PhoneLookup.DISPLAY_NAME}, null, null, null);
            try {
                if (cursor.moveToFirst()) {
                    return cursor.getString(0);
                }
            }finally {
                cursor.close();
            }
            return "";
        }
    }

    /**
     * 根据 contactId 获得 rawContactId
     * @param cr
     * @param contactId
     * @return
     */
    public static long getRawContactId(ContentResolver cr, long contactId) {
        long rawContactId = -1;
        if (contactId > 0) {
            Cursor c = cr.query(RawContacts.CONTENT_URI, RAWID_VERSION,
                    RAWID_CLAUSE, new String[]{
                            String.valueOf(contactId)
                    }, null);

            try {
                if (c != null && c.getCount() > 0) {
                    c.moveToFirst();
                    rawContactId = c.getLong(0);
                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
        }

        return rawContactId;
    }

    /**
     * 更改或增加联系人的头像
     * @param mContext
     * @param mContactId
     * @param photo
     * @return
     */
    public long upDateOrInsertContactPhoto(Context mContext,long mContactId,byte[] photo) {
        ContentValues cv = new ContentValues();
        ContentResolver resolver = mContext.getContentResolver();
        long rawContactId = getRawContactId(resolver,mContactId);
        Bitmap bitmap = getPhotoByContactId(mContext,mContactId);
        if (photo != null ){

            if (bitmap == null){

                cv.put(Contacts.Data.RAW_CONTACT_ID, rawContactId);
                cv.put(Contacts.Data.MIMETYPE, CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
                cv.put(CommonDataKinds.Photo.PHOTO, photo);
                resolver.insert(ContactsContract.Data.CONTENT_URI,
                        cv);

            }else{

                cv.put(CommonDataKinds.Photo.PHOTO, photo);

                String selection = Contacts.Data.RAW_CONTACT_ID + "=? and " + Contacts.Data.MIMETYPE
                        + "=?";
                String[] selectionArgs = new String[] {
                        Long.toString(rawContactId), CommonDataKinds.Photo.CONTENT_ITEM_TYPE };

                resolver.update(ContactsContract.Data.CONTENT_URI, cv, selection,
                        selectionArgs);
            }
        }
        return ContactsDBReader.getContactIdByRaw(resolver, "" + rawContactId);
    }


    public static HashSet<Long> getRawContactIdSet(ContentResolver cr, long contactId) {
        HashSet<Long> set = new HashSet<Long>();

        if (contactId > 0) {
            Cursor c = cr.query(RawContacts.CONTENT_URI, RAWID_VERSION,
                    RAWID_CLAUSE, new String[]{
                            String.valueOf(contactId)
                    }, null);

            try {
                while (c.moveToNext()) {
                    set.add(c.getLong(0));
                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
        }

        return set;
    }

    public static final String[] RAWID_VERSION = new String[]{
            RawContacts._ID, RawContacts.VERSION
    };

    public static final String[] RAW_CONTACTID = new String[]{
            RawContacts.CONTACT_ID
    };

    //String[] phonePro = {
    public static final String[] PHONE_NUMBER = new String[]{
            Phone.NUMBER, Data.MIMETYPE
    };

    public static final String RAWID_CLAUSE = RawContacts.CONTACT_ID + "=?";

    public static long[] getRawContactIdAndVersion(ContentResolver cr, long contactId) {
        long[] ret = new long[2];
        if (contactId > 0) {
            Cursor c = cr.query(RawContacts.CONTENT_URI,
                    RAWID_VERSION, RAWID_CLAUSE, new String[]{
                            String.valueOf(contactId)
                    }, null);

            try {
                if (c != null && c.getCount() > 0) {
                    c.moveToFirst();
                    ret[0] = c.getLong(0); // rawContactId
                    ret[1] = c.getLong(1); // version

                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
        }

        return ret;
    }

    public static long[] getContactIdArr(ContentResolver cr, HashSet<Long> rawIdArr) {

        long[] contactIdArr = new long[rawIdArr.size()];

        StringBuilder sb = new StringBuilder();
        sb.append(RawContacts._ID).append(" in (");

        Iterator<Long> it = rawIdArr.iterator();
        while (it.hasNext()) {
            sb.append(String.valueOf(it.next())).append(",");
        }

        sb.deleteCharAt(sb.length() - 1);
        sb.append(")");

        Cursor c = cr.query(RawContacts.CONTENT_URI,
                RAW_CONTACTID,
                sb.toString(), null, null);

        if (c != null) {
            try {
                for (int j = 0; c.moveToNext(); j++) {
                    contactIdArr[j] = c.getInt(0);
                }
            } finally {
                c.close();
            }
        }

        return contactIdArr;
    }

    public static long getContactIdByRaw(ContentResolver cr, String rawId) {

        long contactId = -1;

        StringBuilder sb = new StringBuilder();
        sb.append(RawContacts._ID).append("=").append(rawId);

        Cursor c = cr.query(RawContacts.CONTENT_URI,
                RAW_CONTACTID,
                sb.toString(), null, null);

        if (c != null) {
            try {
                for (int j = 0; c.moveToNext(); j++) {
                    contactId = c.getLong(0);
                }
            } finally {
                c.close();
            }
        }

        return contactId;
    }

    public static long[] getAllContactsId(Context context) {
        long[] contactIdArr = null;
        Cursor c = context.getContentResolver().query(Contacts.CONTENT_URI,
                new String[]{Contacts._ID},
                null, null, null);
        try {
            if (c != null) {
                contactIdArr = new long[c.getCount()];
                for (int i = 0; c.moveToNext(); i++) {
                    contactIdArr[i] = c.getLong(0);
                }
            }
        } finally {
            c.close();
        }
        return contactIdArr;
    }

    public static Long[] getAllContactsIdLong(Context context) {
        Long[] contactIdArr = null;
        Cursor c = context.getContentResolver().query(Contacts.CONTENT_URI,
                new String[]{Contacts._ID},
                null, null, null);
        try {
            if (c != null) {
                contactIdArr = new Long[c.getCount()];
                for (int i = 0; c.moveToNext(); i++) {
                    contactIdArr[i] = c.getLong(0);
                }
            }
        } finally {
            c.close();
        }
        return contactIdArr;
    }

    public static ArrayList<Long> getAllContactsIdArrayList(Context context) {
        ArrayList<Long> contactIdArr = new ArrayList<Long>();
        Cursor c = context.getContentResolver().query(Contacts.CONTENT_URI,
                new String[]{Contacts._ID},
                null, null, null);
        try {
            if (c != null) {
                for (int i = 0; c.moveToNext(); i++) {
                    contactIdArr.add(c.getLong(0));
                }
            }
        } finally {
            c.close();
        }
        return contactIdArr;
    }

    public static long[] getAllContactsIdWithNoPhone(Context context) {
        long[] contactIdArr = null;
        Cursor cursor = context.getContentResolver().query(Contacts.CONTENT_URI, new String[]{Contacts._ID},
                Constants.CLAUSE_ONLY_PHONES, null, null);
        if (cursor != null) {
            try {
                contactIdArr = new long[cursor.getCount()];
                for (int i = 0; cursor.moveToNext(); i++) {
                    contactIdArr[i] = cursor.getLong(0);
                }
            } finally {
                cursor.close();
            }
        }

        return contactIdArr;
    }

    // 根据分组查询联系人的
    public static final String[] RAW_PROJECTION = new String[]{
            Data.RAW_CONTACT_ID,
    };

    // 根据分组查询联系人的selection
    public static final String RAW_CONTACTS_WHERE = GroupMembership.GROUP_ROW_ID + "=?" + " and "
            + Data.MIMETYPE + "=" + "'" + GroupMembership.CONTENT_ITEM_TYPE + "'";

    public static final String RAW_CONTACTS_IN_NO_GROUP_SELECTION = "1=1) and "
            + Data.RAW_CONTACT_ID + " not in( select " + Data.RAW_CONTACT_ID
            + " from view_data where " + Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE
            + "' ";

    public static final String RAW_CONTACTS_NO_GROUP_SELECTION = "1=1) and "
            + GroupMembership.GROUP_ROW_ID + " not in( ";

    // 查询可显示且未删除的群组的过滤条件
    public static final String VISIBLE_GROUP_SELECTION = Groups.GROUP_VISIBLE
            + "=1 and " + Groups.DELETED + "=0";

    public static final String DATA_GROUP_TYPE = Data.MIMETYPE + " = '" + GroupMembership.CONTENT_ITEM_TYPE + "'";

    /**
     * 根据groupId 获取 在该分组下的联系人的contactId
     *
     * @param mContentProvider
     * @param groupId
     * @return
     * @author gaotong
     */

    public static HashSet<Long> getGroupMembers(ContentResolver mContentProvider, long groupId) {

        HashSet<Long> listRawContactIds = new HashSet<Long>();

        if (groupId > 0) {

            Cursor contacts = mContentProvider.query(Data.CONTENT_URI, null,
                    RAW_CONTACTS_WHERE, new String[]{String.valueOf(groupId)}, null);

            try {
                // 获得联系人的电话号码
                if (contacts != null && contacts.moveToFirst()) {

                    do {
                        long rawContactId = contacts
                                .getLong(contacts.getColumnIndex(GroupMembership.RAW_CONTACT_ID));
                        /*int visible = contacts.getInt(contacts.getColumnIndex(Data.IN_VISIBLE_GROUP));
                        long contactId = contacts
                                .getLong(contacts.getColumnIndex(GroupMembership.CONTACT_ID));
                        String contactName = getContactNameByContactId(mContentProvider, contactId);
                        Log.i(TAG, contactName);*/
                        listRawContactIds.add(rawContactId);
                    } while (contacts.moveToNext());
                }
            } catch (Exception e) {

            } finally {
                if (contacts != null) {
                    contacts.close();
                }
            }

        }

        return listRawContactIds;

    }

    /**
     * 获取对应联系人（contactId）的第一个手机号
     *
     * @param mContentProvider
     * @param contactId
     * @author gaotong
     */
    public static ArrayList<String> getContactNumbers(ContentResolver mContentProvider, String contactId) {

        ArrayList<String> phoneNumbers = new ArrayList<String>();

        if (contactId != null) {
            Cursor number = mContentProvider.query(
                    Phone.CONTENT_URI, PHONE_NUMBER,
                    Phone.CONTACT_ID + " = " + contactId, null,
                    null);

            try {

                // 获得联系人的电话号码
                if (number != null && number.moveToFirst()) {

                    do {
                        // 遍历所有的电话号码
                        String phoneNumber = number.getString(number
                                .getColumnIndex(Phone.NUMBER));
                        phoneNumbers.add(phoneNumber);
                    } while (number.moveToNext());

                }
            } finally {
                if (number != null) {
                    number.close();
                }
            }

        }

        return phoneNumbers;
    }

    public static ArrayList<String> getPhoneNumberByRawContactId(Context context, long rawContactId) {
        Cursor cursor = null;
        PhoneNumberArea area = PhoneNumberArea.getInstance(context);
        ArrayList<String> result = null;
        try {
            cursor = context.getContentResolver().query(Data.CONTENT_URI, DATA_PROJECTION, Data.RAW_CONTACT_ID + "=?", new String[]{"" + rawContactId}, null);
            if (cursor != null && cursor.getCount() > 0) {
                result = new ArrayList<String>();
                boolean isTrue = cursor.moveToFirst();
                while (isTrue) {
                    String mimetype = cursor.getString(cursor.getColumnIndex(Data.MIMETYPE));
                    if(!StringUtil.isEmpty(mimetype) && mimetype.equals(Phone.CONTENT_ITEM_TYPE)){
                        String phoneNumber = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
                        result.add(area.replaceIpCall(phoneNumber));
                    }
                    isTrue = cursor.moveToNext();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return result;
    }

    public static ArrayList<Long> getDataIdByPhoneNumber(Context context, long rawContactId) {
        Cursor cursor = null;
        ArrayList<Long> result = new ArrayList<Long>();
        PhoneNumberArea area = PhoneNumberArea.getInstance(context);
        try {
            cursor = context.getContentResolver().query(Data.CONTENT_URI, DATA_PROJECTION, Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=?", new String[]{"" + rawContactId, Phone.CONTENT_ITEM_TYPE}, null);
            if (cursor != null && cursor.getCount() > 0) {
                boolean isTrue = cursor.moveToFirst();
                while (isTrue) {
                    String num = cursor.getString(cursor.getColumnIndex(Phone.NUMBER));
                    String formatedNum = area.replaceIpCall(num);
                    if(!StringUtil.isEmpty(formatedNum)){
                        result.add(cursor.getLong(cursor.getColumnIndex(Data._ID)));
                    }
                    isTrue = cursor.moveToNext();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return result;
    }

    public static ArrayList<NumLabel> getOneContactNumberLabel(ContentResolver mContentProvider, String contactId) {

        ArrayList<NumLabel> phoneNumbers = new ArrayList<NumLabel>();

        if (contactId != null) {
            Cursor number = mContentProvider.query(
                    Phone.CONTENT_URI, NUM_LABEL,
                    Phone.CONTACT_ID + " = " + contactId, null,
                    null);

            try {

                // 获得联系人的电话号码
                if (number != null && number.moveToFirst()) {

                    int numIndex = number.getColumnIndex(Phone.NUMBER);
                    int labelIndex = number.getColumnIndex(Phone.DATA2);

                    do {
                        NumLabel numLabel = new NumLabel();
                        numLabel.num = number.getString(numIndex);
                        numLabel.label = number.getInt(labelIndex);

                        phoneNumbers.add(numLabel);
                    } while (number.moveToNext());

                }
            } finally {
                if (number != null) {
                    number.close();
                }
            }

        }

        return phoneNumbers;
    }

    public static class NumLabel {
        public int label;
        public String num;
    }

    private static final String[] NUM_LABEL = new String[]{Phone.NUMBER, "data2"};

    public static ArrayList<NumLabel> getContactNumberLabel(ContentResolver mContentProvider, String contactId) {

        ArrayList<NumLabel> phoneNumbers = new ArrayList<NumLabel>();

        if (contactId != null) {
            Cursor cur = mContentProvider.query(
                    Phone.CONTENT_URI, NUM_LABEL,
                    Phone.CONTACT_ID + " = " + contactId, null,
                    null);

            try {
                if (cur != null && cur.moveToFirst()) {
                    int numIndex = cur.getColumnIndex(Phone.NUMBER);
                    int labelIndex = cur.getColumnIndex(Phone.DATA2);
                    do {
                        NumLabel numLabel = new NumLabel();
                        numLabel.num = cur.getString(numIndex);
                        numLabel.label = cur.getInt(labelIndex);

                        phoneNumbers.add(numLabel);
                    } while (cur.moveToNext());

                }
            } finally {
                if (cur != null) {
                    cur.close();
                }
            }

        }

        return phoneNumbers;
    }

    public static HashMap<String, String> getPhoneType(Context context, String contactId) {

//        ArrayList<String> phoneNumbers = new ArrayList<String>();
        HashMap<String, String> phoneMap = new HashMap<String, String>();

        if (contactId != null) {

            Cursor number = context.getContentResolver().query(
                    Phone.CONTENT_URI, null,
                    Phone.CONTACT_ID + " = " + contactId, null,
                    null);
            // + " AND " + Phone.TYPE + " = " + Phone.TYPE_MOBILE, null, null);

            try {

                // 获得联系人的电话号码
                if (number != null && number.moveToFirst()) {

                    do {
                        // 遍历所有的电话号码
                        String phoneNumber = number.getString(number.getColumnIndex(Phone.NUMBER));
                        int type = number.getInt(number.getColumnIndex(Phone.TYPE));
                        String phoneLabel = Phone.getTypeLabel(context.getResources(), type, "").toString();

                        phoneMap.put(phoneNumber, phoneLabel);

                    } while (number.moveToNext());

                }
            } finally {
                if (number != null) {
                    number.close();
                }
            }

        }

        return phoneMap;
    }

//    public static String getFirstMobilePhoneNumber(Context context, long contactId) {
//
//        PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(context.getApplicationContext());
//        Person person = preferenceUtil.getPerson(contactId);
//
//        com.lzx.iteam.util.PhoneNumberArea phoneNumberArea = com.lzx.iteam.util.PhoneNumberArea
//                .getInstance(context.getApplicationContext());
//        if (person == null) {
//            ArrayList<String> phoneNumbers = ContactsDBReader.getContactNumbers(
//                    context.getContentResolver(), Long.toString(contactId));
//            for (String numberElement : phoneNumbers) {
//                if (phoneNumberArea.isMobilePhone(numberElement)) {
//                    return numberElement;
//                }
//            }
//        } else {
//            List<Person.PhoneNumber> phoneNumberArray = person.getPhoneList();
//            if (phoneNumberArray != null && phoneNumberArray.size() > 0) {
//                for (Person.PhoneNumber number : phoneNumberArray) {
//                    String numberElement = number.getNumber();
//                    if (phoneNumberArea.isMobilePhone(numberElement)) {
//                        return numberElement;
//                    }
//                }
//            }
//        }
//
//        return null;
//    }

    public static String getFirstMobilePhoneNumber(Context context, long contactId,
                                                   boolean isPhoneNum) {

//        PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(context.getApplicationContext());
//        Person person = preferenceUtil.getPerson(contactId);
//
        com.lzx.iteam.util.PhoneNumberArea phoneNumberArea = com.lzx.iteam.util.PhoneNumberArea
                .getInstance(context.getApplicationContext());
//        if (person == null) {
        ArrayList<NumLabel> phoneNumbers = ContactsDBReader.getOneContactNumberLabel(
                context.getContentResolver(), Long.toString(contactId));


        for (NumLabel numberLabel : phoneNumbers) {
            String numberElement = numberLabel.num;
            int label = numberLabel.label;
            numberElement = phoneNumberArea.replaceIpCall(numberElement);
            if (phoneNumberArea.isMobilePhone(numberElement, label)) {
                return numberElement;
            }
        }
//        } else {
//            List<Person.PhoneNumber> phoneNumberArray = person.getPhoneList();
//            if (phoneNumberArray != null && phoneNumberArray.size() > 0) {
//                for (Person.PhoneNumber number : phoneNumberArray) {
//                    String numberElement = number.getNumber();
//
//                    numberElement = phoneNumberArea.replaceIpCall(numberElement);
//                    if (isPhoneNum) {
//                        if (phoneNumberArea.isMobilePhone(numberElement)) {
//                            return numberElement;
//                        }
//
//                    } else {
//                        return numberElement;
//                    }
//                }
//            }
//        }

        return null;
    }

    /**
     * 获取对应联系人（contactId）所有号码
     *
     * @param mContentProvider
     * @param contactId
     * @author gaotong
     */
    public static List<String> getContactAllNumbers(ContentResolver mContentProvider, String contactId) {

        List<String> listNumbers = new ArrayList<String>();
        String phoneNumber = "";

        if (contactId != null) {

            Cursor cursor = mContentProvider.query(
                    Phone.CONTENT_URI, PHONE_NUMBER,
                    Phone.CONTACT_ID + " = " + contactId, null, null);

            try {

                // 获得联系人的电话号码
                while (cursor != null && cursor.moveToNext()) {
                    // 遍历所有的电话号码
                    phoneNumber = cursor.getString(cursor
                            .getColumnIndex(Phone.NUMBER));
                    listNumbers.add(phoneNumber);
                }

            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }

        }

        return listNumbers;
    }


    /**
     * 获取对应分组（groupId）的联系人的第一个手机号
     *
     * @param mContentProvider
     * @param groupId
     * @author gaotong
     */
    public static Map<String, ArrayList<NumLabel>> getGroupContactAllNumbers(ContentResolver mContentProvider,
                                                                             long groupId) {

        HashSet<Long> rawContactIdList = getGroupMembers(mContentProvider, groupId);
        if (rawContactIdList == null || rawContactIdList.size() == 0) {
            return null;
        }

        long[] contactIdArray = ContactsDBReader.getContactIdArr(mContentProvider, rawContactIdList);
        Map<String, ArrayList<NumLabel>> allContactNubmers = new HashMap<String, ArrayList<NumLabel>>();

        for (Long contactId : contactIdArray) {
            String contactIdStr = String.valueOf(contactId);
            ArrayList<NumLabel> number = getContactNumberLabel(mContentProvider, contactIdStr);
            allContactNubmers.put(contactIdStr, number);
        }

        return allContactNubmers;

    }

    public static boolean isInBlackList(Context context, ArrayList<String> numbers) {
        /*if (numbers == null) {
            return false;
        }
        for (String callLogNum : numbers) {
            Cursor cursor = context.getContentResolver().query(CloudContactsDB.CommunicationRule.CONTENT_URI,
                    new String[]{
                            CloudContactsDB.CommunicationRule.PHONE_NUMBER, CloudContactsDB.CommunicationRule.PATTERN
                    }, CloudContactsDB.CommunicationRule.PHONE_NUMBER + " = '" + callLogNum + "'", null, null);
            try {
                if (cursor != null) {
                    while (cursor.moveToNext()) {
                        String phoneNumber = cursor.getString(0);
                        Log.d("ActionContactsCenter", "the phonenumber is " + phoneNumber);
                        int pattern = cursor.getInt(1);
                        if ((pattern & 1 << Constants.COMMUNICATION_STATUS_IN_SMS_BLACK) != 0
                                || (pattern & 1 << Constants.COMMUNICATION_STATUS_IN_TELEPHONY_BLACK) != 0
                                || (pattern & 1 << Constants.COMMUNICATION_STATUS_IN_BLACK) != 0) {
                            return callLogNum.equals(phoneNumber);
                        }
                    }
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }*/

        return false;
    }

    public static Map<String, ArrayList<NumLabel>> getPhoneNumberByContactId(ContentResolver cr, HashSet<String> contactsId) {
        Map<String, ArrayList<NumLabel>> allContactNubmers = new HashMap<String, ArrayList<NumLabel>>();

        for (String contactId : contactsId) {
            ArrayList<NumLabel> number = getContactNumberLabel(cr, contactId);
            allContactNubmers.put(contactId, number);
        }

        return allContactNubmers;
    }

    public static ArrayList<String> getPhoneNumberByContactIds(ContentResolver cr, ArrayList<Long> ids) {
        ArrayList<String> result = new ArrayList<String>();
        for (long contactId : ids) {
            if (contactId != 0) {
                Cursor cur = cr.query(
                        Phone.CONTENT_URI, NUM_LABEL,
                        Phone.CONTACT_ID + " = " + contactId, null,
                        null);

                try {
                    if (cur != null && cur.moveToFirst()) {
                        int numIndex = cur.getColumnIndex(Phone.NUMBER);
                        do {
                            String num = cur.getString(numIndex);
                            result.add(num);
                        } while (cur.moveToNext());

                    }
                } finally {
                    if (cur != null) {
                        cur.close();
                    }
                }

            }
        }
        return result;
    }



    public static Map<String, ArrayList<NumLabel>> getPhoneNumberByContactId(ContentResolver mContentProvider, long[] contactIds) {

        Map<String, ArrayList<NumLabel>> allContactNubmers = new HashMap<String, ArrayList<NumLabel>>();

        for (long contactId : contactIds) {
            String contactIdStr = String.valueOf(contactId);
            ArrayList<NumLabel> number = getContactNumberLabel(mContentProvider, contactIdStr);
            allContactNubmers.put(contactIdStr, number);
        }

        return allContactNubmers;
    }

    private final static String[] COLUMNS = new String[]{
            Groups.ACCOUNT_NAME, Groups.ACCOUNT_TYPE, Groups._ID, Groups.TITLE,
            Groups.SUMMARY_COUNT,
    };

    public final static int ACCOUNT_NAME = 0;

    public final static int ACCOUNT_TYPE = 1;

    public final static int GROUP_ID = 2;

    public final static int TITLE = 3;

    private static final Uri GROUP_LIST_URI = Groups.CONTENT_SUMMARY_URI;

    public static HashMap<String, GroupInfo> mGroupList = new HashMap<String, GroupInfo>();

    public static int ALL_CONTACTS_NUMBER = 0;

    public static void resetAllContactsNumber(Context context) {
//        DialerApp mDialerApp;
        PreferenceUtil mPreferenceUtil;
//        mDialerApp = (DialerApp) context.getApplicationContext();
        mPreferenceUtil = PreferenceUtil.getInstance(context);

        boolean ifShowPeopleNoPhone = mPreferenceUtil.getBoolean(PreferenceUtil.SHOW_PEOPLE_NO_PHONENUMBER, false);

        Cursor cursor = context.getContentResolver().query(Contacts.CONTENT_URI, null,
                ifShowPeopleNoPhone ? null : Constants.CLAUSE_ONLY_PHONES, null, null);
        if (cursor != null) {
            try {
                ContactsDBReader.ALL_CONTACTS_NUMBER = cursor.getCount();
                Log.i("getCount","===="+cursor.getCount());
            } finally {
                cursor.close();
            }
        }
        mPreferenceUtil.save(PreferenceUtil.CONTACT_NUMBERS,ContactsDBReader.ALL_CONTACTS_NUMBER+"");
//      ContactsDBReader.getGroupHash(context.getContentResolver());
        ContactsDBReader.getNoGroupsSet(context);
    }

    public static void getGroupHash(ContentResolver cr) {
        /**
         * Attention: we get all group under any account
         * 在目前的实现中我们获取所有的group信息，以下的注释 为获取account不为空的分组信息
         */
        /*
         * Cursor cursor = cr.query(GROUP_LIST_URI, COLUMNS, Groups.ACCOUNT_TYPE
         * + " NOT NULL AND " + Groups.ACCOUNT_NAME + " NOT NULL AND " +
         * Groups.DELETED + "=0", null, Groups.ACCOUNT_TYPE + ", " +
         * Groups.ACCOUNT_NAME + ", " + Groups.TITLE +
         * " COLLATE LOCALIZED ASC");
         */
        Cursor cursor = cr.query(GROUP_LIST_URI, COLUMNS, Groups.DELETED + "=0", null,
                Groups.ACCOUNT_TYPE + ", " + Groups.ACCOUNT_NAME + ", " + Groups.TITLE
                        + " COLLATE LOCALIZED ASC");

        if (cursor != null) {
            try {
                while (cursor.moveToNext()) {
                    String accountName = cursor.getString(ACCOUNT_NAME);
                    String accountType = cursor.getString(ACCOUNT_TYPE);

                    long groupId = cursor.getLong(GROUP_ID);
                    String title = cursor.getString(TITLE);

                    //change title name
                    if (!TextUtils.isEmpty(title)) {
                        if (title.equals(Constants.GOOGLE_MY_CONTACTS_GROUP)) {
                            title = Constants.GOOGLE_MY_CONTACTS_GROUP_NAME;
                        } else if (title.equals(Constants.GOOGLE_CO_WORKERS_GROUP)) {
                            title = Constants.GOOGLE_CO_WORKERS_GROUP_NAME;
                        } else if (title.equals(Constants.GOOGLE_FAMILY_GROUP)) {
                            title = Constants.GOOGLE_FAMILY_GROUP_NAME;
                        } else if (title.equals(Constants.GOOGLE_FRIENDS_GROUP)) {
                            title = Constants.GOOGLE_FRIENDS_GROUP_NAME;
                        } else if (title.equals(Constants.GOOGLE_STARRED_GROUP)) {
                            title = Constants.GOOGLE_STARRED_GROUP_NAME;
                        }
                    } else {
                        title = "";
                    }

                    if (!mGroupList.containsKey(Long.toString(groupId))) {
                        GroupInfo group = new GroupInfo();
                        group.mGroupAccountName = accountName;
                        group.mGroupAccountType = accountType;
                        group.mGroupID = groupId;
                        group.mGroupTitle = title;
//                        group.mMembersCount = getGroupMembers(cr, groupId).size();

                        mGroupList.put(Long.toString(groupId), group);
                    } else {
                        GroupInfo groupInfo = mGroupList.get(Long.toString(groupId));
                        if (groupInfo.mGroupTitle != title) {
                            groupInfo.mGroupTitle = title;
                        }
                    }

                }
            } finally {
                cursor.close();
            }
        }
//        HashMap<String, GroupInfo> groupListTemp = new HashMap<String, ContactsDBReader.GroupInfo>(mGroupList);
        Iterator<String> it = mGroupList.keySet().iterator();
        while (it.hasNext()) {
            String key = it.next();
            GroupInfo group = mGroupList.get(key);
            group.mMembersCount = getGroupMembers(cr, group.mGroupID).size();
        }
    }

    public static HashSet<String> mNoGroupsSet = new HashSet<String>();

    public static void getNoGroupsSet(Context c) {

        Set<String> groupIds = new HashSet<String>();
        Set<String> noPhoneNumGroup = new HashSet<String>();

        mNoGroupsSet.clear();
        // Get the group membership
        Cursor gmCursor = c.getContentResolver().query(Data.CONTENT_URI, DATA_TYPE,
                DATA_GROUP_TYPE, null, null);
        try {
            if (gmCursor != null && gmCursor.getCount() > 0) {
                while (gmCursor.moveToNext()) {
                    String groupTitle = gmCursor.getString(2);
                    // We need to pre-parse the group ids to find all the ones
                    // that
                    // have a group
                    if (groupTitle != null && !"-1".equals(groupTitle) && mGroupList != null
                            && mGroupList.keySet().contains(groupTitle)) {
                        groupIds.add(gmCursor.getString(0));
                    }
                }
            }
        } finally {
            if (gmCursor != null) {
                gmCursor.close();
            }
        }

        // should show people no phone
        PreferenceUtil mPreferenceUtil;
        mPreferenceUtil = PreferenceUtil.getInstance(c);
        boolean ifShowPeopleNoPhone = mPreferenceUtil.get(
                PreferenceUtil.SHOW_PEOPLE_NO_PHONENUMBER, Boolean.class);
        if (!ifShowPeopleNoPhone) {
            // String inVisibleGroup = Contacts.IN_VISIBLE_GROUP + "=1";
            gmCursor = c.getContentResolver().query(Contacts.CONTENT_URI, CONTACT_ID,
                    Constants.CLAUSE_NO_PHONE, null, null);
            try {
                while (gmCursor != null && gmCursor.moveToNext()) {
                    noPhoneNumGroup.add(String.valueOf(gmCursor.getLong(0)));
                }
            } finally {
                if (gmCursor != null) {
                    gmCursor.close();
                }
            }
        }

        gmCursor = c.getContentResolver().query(Contacts.CONTENT_URI,
                CONTACT_ID,
                ifShowPeopleNoPhone ? null : Constants.CLAUSE_ONLY_PHONES, null, null);
        try {
            if (gmCursor == null || gmCursor.getCount() <= 0) {
                return;
            }

            if (noPhoneNumGroup.size() > 0) {
                while (gmCursor.moveToNext()) {
                    String id = gmCursor.getString(0);
                    if (!mNoGroupsSet.contains(id) && !groupIds.contains(id)
                            && !noPhoneNumGroup.contains(id)) {
                        mNoGroupsSet.add(id);
                    }
                }
            } else {
                while (gmCursor.moveToNext()) {
                    String id = gmCursor.getString(0);
                    if (!mNoGroupsSet.contains(id) && !groupIds.contains(id)) {
                        mNoGroupsSet.add(id);
                    }
                }
            }
        } finally {
            if (gmCursor != null) {
                gmCursor.close();
            }
        }

        groupIds.clear();
        groupIds = null;
        noPhoneNumGroup.clear();
        noPhoneNumGroup = null;
    }

    public long createGroupWithAccount(final ContentResolver cr, final Account account,
                                       String title, int visible) {
        ContentValues values = new ContentValues();
        values.put(Groups.SOURCE_ID, "");
        values.put(Groups.TITLE, title);
        values.put(Groups.GROUP_VISIBLE, visible);

        Uri uri = Groups.CONTENT_URI;
        if (account != null) {
            uri = uri.buildUpon().appendQueryParameter(RawContacts.ACCOUNT_NAME, account.name)
                    .appendQueryParameter(RawContacts.ACCOUNT_TYPE, account.type).build();
        }

        return ContentUris.parseId(cr.insert(uri, values));
    }

    public static String getDisplayNameByNumber(Context c, String phoneNum) {
        // By default we will show the phone number
        String displayName = phoneNum;
        HashSet<Long> contactIdSet = getContactIdByPhoneNumber(
                c, phoneNum);

        if (contactIdSet == null || contactIdSet.size() == 0)
            return displayName;

        for (Long contactId : contactIdSet) {
            String name = getContactNameByContactId(
                    c.getContentResolver(), contactId);
            if (!TextUtils.isEmpty(name)) {
                displayName = name;
                break;
            }
        }

        return displayName;
    }

    public static long createGroup(final ContentResolver cr, String groupName) {

        final ContentValues values = new ContentValues();
        values.put(Groups.TITLE, groupName);
        Uri groupUri = cr.insert(Groups.CONTENT_URI, values);
        return ContentUris.parseId(groupUri);
    }

    public static boolean removeGroup(final ContentResolver cr, long groupRowId) {
        String groupRowIdStr = String.valueOf(groupRowId);
        int counter = 0;

        counter += cr.delete(Groups.CONTENT_URI, Groups._ID + "=?", new String[]{
                groupRowIdStr
        });

        counter += cr.delete(Data.CONTENT_URI, Data.MIMETYPE + "=? AND "
                + GroupMembership.GROUP_ROW_ID + "=?", new String[]{
                GroupMembership.CONTENT_ITEM_TYPE, groupRowIdStr
        });

        return counter > 0;
    }

    /**
     * 删除联系人 ContactsContract.CALLER_IS_SYNCADAPTER true 直接从库中删除联系人信息
     * 不是将deleted标志位置1
     *
     * @param cr
     * @param personUri modify by gaotong
     */
    public static boolean removeContactByContactId(ContentResolver cr, long contactId) {
        // 这个是删除contacts 表 还是 raw_contacts 表 还要确认
        boolean result = false;
        Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);

        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

        Uri uri = contactUri.buildUpon()
                .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();

        ops.add(ContentProviderOperation.newDelete(uri).build());

        try {
            cr.applyBatch(ContactsContract.AUTHORITY, ops);
            result = true;
        } catch (RemoteException e) {
            e.printStackTrace();
            result = false;
        } catch (OperationApplicationException e) {
            e.printStackTrace();
            result = false;
        }

        //remove local contactInfo
        //get shared address
        /*String selection = ContactInfo.CONTACT_ID + "=? ";
        String[] selectionArgs = {
                String.valueOf(raw_contactId)
        };
        cr.delete(ContactInfo.CONTENT_URI, selection, selectionArgs);*/
        return result;

    }

    public static Uri addToGroup(ContentResolver cr, long contactId, long groupId) {

        long rawContactId = getRawContactId(cr, contactId);
        if (rawContactId == -1)
            return null;

//        removeFromGroup(cr, rawContactId, groupId);

        ContentValues values = new ContentValues();
        values.put(GroupMembership.RAW_CONTACT_ID, rawContactId);
        values.put(GroupMembership.GROUP_ROW_ID, groupId);
        values.put(GroupMembership.MIMETYPE,
                GroupMembership.CONTENT_ITEM_TYPE);

        return cr.insert(Data.CONTENT_URI, values);

    }

    public static Uri addToGroupByRawId(ContentResolver cr, long rawContactId, long groupId) {

        ContentValues values = new ContentValues();
        values.put(GroupMembership.RAW_CONTACT_ID, rawContactId);
        values.put(GroupMembership.GROUP_ROW_ID, groupId);
        values.put(GroupMembership.MIMETYPE,
                GroupMembership.CONTENT_ITEM_TYPE);

        return cr.insert(Data.CONTENT_URI, values);

    }

    public static void removeFromGroup(ContentResolver cr, long contactId, long groupId) {
        long rawContactId = getRawContactId(cr, contactId);
        if (rawContactId == -1)
            return;

        cr.delete(
                Data.CONTENT_URI,
                Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=? AND "
                        + GroupMembership.GROUP_ROW_ID + "=?",
                new String[]{
                        String.valueOf(rawContactId), GroupMembership.CONTENT_ITEM_TYPE,
                        String.valueOf(groupId)
                });
    }

    /**
     * 根据contactId 获取分组row_id
     *
     * @param cr
     * @param contactId
     * @return
     */
    public static ArrayList<Long> getGroupIdByContactId(ContentResolver cr, long contactId) {
        long rawContactId = getRawContactId(cr, contactId);
        if (rawContactId == -1)
            return null;
        ArrayList<Long> groups = new ArrayList<Long>();

        Cursor cursor = cr.query(Data.CONTENT_URI, new String[]{
                GroupMembership.GROUP_ROW_ID
        }, DATA_MIMETYPE_RAWCONTACTID, new String[]{
                String.valueOf(rawContactId), GroupMembership.CONTENT_ITEM_TYPE,

        }, null);

        try {
            while (cursor.moveToNext()) {

                long groupId = cursor
                        .getLong(cursor
                                .getColumnIndex(GroupMembership.GROUP_ROW_ID));

                groups.add(groupId);

            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return groups;
    }

    public static ArrayList<String> getGroupIdByRawContactId(ContentResolver cr, long rawContactId) {
        ArrayList<String> groups = new ArrayList<String>();

        Cursor cursor = cr.query(Data.CONTENT_URI, new String[]{
                GroupMembership.GROUP_ROW_ID
        }, DATA_MIMETYPE_RAWCONTACTID, new String[]{
                String.valueOf(rawContactId), GroupMembership.CONTENT_ITEM_TYPE,

        }, null);

        try {
            while (cursor.moveToNext()) {

                String groupId = cursor
                        .getString(cursor
                                .getColumnIndex(GroupMembership.GROUP_ROW_ID));

                groups.add(groupId);

            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return groups;
    }


    public static void renameGroup(ContentResolver cr, long groupId, String newName) {

        if (groupId == -1) {
            return;
        }

        ContentValues values = new ContentValues();
        values.put(Groups.TITLE, newName);
        final Uri groupUri = ContentUris.withAppendedId(Groups.CONTENT_URI, groupId);
        cr.update(groupUri, values, null, null);
    }

    public static final String DATA_MIMETYPE_CONTACTID = Data.MIMETYPE + " = ? and " + Data.CONTACT_ID + " = ? ";
    public static final String DATA_MIMETYPE_RAWCONTACTID = Data.RAW_CONTACT_ID + "=? AND " + Data.MIMETYPE + "=? ";

    public static String getContactNameByContactId(ContentResolver cr, long contactId) {
        Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
        Uri methodUri = Uri.withAppendedPath(contactUri, Contacts.Data.CONTENT_DIRECTORY);
        String[] whereNameParams = new String[]{
                StructuredName.CONTENT_ITEM_TYPE,
                String.valueOf(contactId)
        };
        Cursor nameCur = cr.query(methodUri, new String[]{"data1"}, DATA_MIMETYPE_CONTACTID,
                whereNameParams, null);
        String displayName = null;
        try {
            if (nameCur.moveToFirst()) {
                displayName = nameCur
                        .getString(nameCur
                                .getColumnIndex(StructuredName.DISPLAY_NAME));
            }
        } finally {
            nameCur.close();
        }

        return displayName;
    }


    public static final String selection = Contacts._ID + " = ? ";

    public static String getDisplayNameFromContacts(ContentResolver cr, long contactId) {
        String[] whereNameParams = new String[]{
                String.valueOf(contactId)
        };
        Cursor nameCur = cr.query(Contacts.CONTENT_URI, null, selection, whereNameParams, null);
        String displayName = null;
        try {
            while (nameCur.moveToNext()) {
                displayName = nameCur.getString(nameCur.getColumnIndex(Contacts.DISPLAY_NAME));
            }
        } finally {
            nameCur.close();
        }

        return displayName;
    }

    public static boolean checkContactNameExistByID(ContentResolver cr, long contactId) {
        String[] whereNameParams = new String[]{
                StructuredName.CONTENT_ITEM_TYPE,
                String.valueOf(contactId)
        };
        Cursor nameCur = cr.query(Data.CONTENT_URI, null, DATA_MIMETYPE_CONTACTID,
                whereNameParams, null);
        String familyName = null;
        String givenName = null;
        String middleName = null;
        try {
            while (nameCur.moveToNext()) {
                familyName = nameCur.getString(nameCur
                        .getColumnIndex(StructuredName.FAMILY_NAME));
                givenName = nameCur.getString(nameCur
                        .getColumnIndex(StructuredName.GIVEN_NAME));
                middleName = nameCur.getString(nameCur
                        .getColumnIndex(StructuredName.MIDDLE_NAME));
            }
        } finally {
            nameCur.close();
        }

        if (StringUtil.isEmpty(familyName) && StringUtil.isEmpty(givenName) && StringUtil.isEmpty(middleName)) {
            return false;
        }

        return true;
    }

    static final int IMAGE_SIZE = 80;
    private static Canvas mCanvas = new Canvas();
    private static Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    /**
     * The radius of the oval used to round the corners.
     */
    private static final float ROUND = 5.0f;

    public static Bitmap getPhoto(Context context, final long aPhotoId) {
        Bitmap photo = null;
        try {
            photo = ContactsUtils.loadContactPhoto(context, aPhotoId, null);
            // 使用缺省
            if (photo == null) {
                return null;
            }
            /** Image size in dp. */
            int sImageSize = (int) (IMAGE_SIZE * ImageUtil.getDensity(context));
            RectF mRect = new RectF(0, 0, sImageSize, sImageSize);
            Bitmap scaledBmp = Bitmap.createScaledBitmap(photo, sImageSize, sImageSize, true);
            photo.recycle();
            photo = ImageUtil.createRoundBitmap(scaledBmp, mCanvas, mPaint, mRect, ROUND);
            scaledBmp.recycle();
        } catch (OutOfMemoryError e) {
            // Not enough memory for the photo, do nothing.
        }

        return photo;
    }

    /**
     * 根据 contactId 得到头像
     * @param context
     * @param contactId
     * @return
     */
    public static Bitmap getRoundPhotoByContactId(Context context, final long contactId) {

        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_URI, Long.toString(contactId));
        Uri photoUri = Uri.withAppendedPath(contactUri,
                Contacts.Data.CONTENT_DIRECTORY);
        Cursor photoCursor = context.getContentResolver().query(photoUri, new String[]{CommonDataKinds.Photo.PHOTO},
                Data.MIMETYPE + "=?", new String[]{
                        CommonDataKinds.Photo.CONTENT_ITEM_TYPE
                }, null);

        photoCursor.moveToFirst();
        Bitmap photo = null;

        if (photoCursor != null && photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
            byte[] photoData = photoCursor.getBlob(0);
            photo = BitmapFactory.decodeByteArray(photoData, 0,
                    photoData.length, null);
        }

        photoCursor.close();
        if (photo == null) return null;


        /** Image size in dp. */
        int sImageSize = (int) (IMAGE_SIZE * ImageUtil.getDensity(context));
        RectF mRect = new RectF(0, 0, sImageSize, sImageSize);
        Bitmap scaledBmp = Bitmap.createScaledBitmap(photo, sImageSize, sImageSize, true);
        photo.recycle();
        photo = ImageUtil.createRoundBitmap(scaledBmp, mCanvas, mPaint, mRect, ROUND);
        scaledBmp.recycle();


        return photo;
    }

    /**
     * 根据 contactId 得到头像
     * @param context
     * @param contactId
     * @return
     */
    public static Bitmap getPhotoByContactId(Context context, final long contactId) {

        Uri contactUri = Uri.withAppendedPath(Contacts.CONTENT_URI, Long.toString(contactId));
        Uri photoUri = Uri.withAppendedPath(contactUri,
                Contacts.Data.CONTENT_DIRECTORY);
        Cursor photoCursor = context.getContentResolver().query(photoUri, new String[]{CommonDataKinds.Photo.PHOTO},
                Data.MIMETYPE + "=?", new String[]{
                        CommonDataKinds.Photo.CONTENT_ITEM_TYPE
                }, null);

        photoCursor.moveToFirst();
        Bitmap photo = null;

        if (photoCursor != null && photoCursor.moveToFirst() && !photoCursor.isNull(0)) {
            byte[] photoData = photoCursor.getBlob(0);
            photo = BitmapFactory.decodeByteArray(photoData, 0,
                    photoData.length, null);
        }

        photoCursor.close();
        if (photo == null) return null;

        return photo;
    }


    /**
     * 插入黑白名单
     *
     * @param cr
     * @param phoneNumber
     * @param contactID
     * @param contactName
     * @param insertToBlacklist
     */
    public static void insertCommunicationRule(ContentResolver cr, List<String> phoneNumbers,
                                               long contactID, String contactName, boolean insertToBlacklist) {
        /*if (phoneNumbers == null || phoneNumbers.size() == 0) return;
        ContentValues values = new ContentValues();
        values.put(CommunicationRule.CONTACT_ID, contactID);
        int pattern = 0;
        if (insertToBlacklist) {
            pattern = (1 << Constants.COMMUNICATION_STATUS_IN_BLACK
                    | 1 << Constants.COMMUNICATION_STATUS_IN_SMS_BLACK | 1 << Constants.COMMUNICATION_STATUS_IN_TELEPHONY_BLACK);
        } else {
            pattern = (1 << Constants.COMMUNICATION_STATUS_IN_WHITE
                    | 1 << Constants.COMMUNICATION_STATUS_IN_SMS_WHITE | 1 << Constants.COMMUNICATION_STATUS_IN_TELEPHONY_WHITE);
        }
        values.put(CommunicationRule.PATTERN, pattern);
        values.put(CommunicationRule.CONTACT_NAME, contactName);
        for (int i = 0; i < phoneNumbers.size(); i++) {
            values.put(CommunicationRule.PHONE_NUMBER, phoneNumbers.get(i));
            cr.insert(CommunicationRule.CONTENT_URI, values);
        }*/

    }

    public static void insertCommunicationRule(ContentResolver cr, String phoneNumber,
                                               long contactID, String contactName, int pattern) {
        /*ContentValues values = new ContentValues();
        values.put(CommunicationRule.CONTACT_ID, contactID);
        values.put(CommunicationRule.PATTERN, pattern);
        values.put(CommunicationRule.CONTACT_NAME, contactName);
        values.put(CommunicationRule.PHONE_NUMBER, phoneNumber);

        cr.insert(CommunicationRule.CONTENT_URI, values);*/
    }

    public static void deleteCommunicationRule(ContentResolver cr, long contactId) {
        /*Uri toDeleteUri = ContentUris.withAppendedId(CommunicationRule.CONTENT_URI, contactId);
        cr.delete(toDeleteUri, null, null);*/
    }

    public static class NumberType {
        public String phone = "";

        // 0 代表黑名单  1 代表白名单
        public int type = 0;

        public NumberType(String phone, int type) {
            if (!TextUtils.isEmpty(phone)) {
                this.phone = phone;
            }
            this.type = type;
        }
    }

    /**
     * 查询存在与黑白名单中的所有号码
     *
     * @param cr
     * @param contactId
     * @return
     * @author gaotong
     */
    public static List<NumberType> selectCommunicationRuleAllPhones(ContentResolver cr) {
        List<NumberType> allNumbers = new ArrayList<NumberType>();
        /*Cursor cursor = null;
        int blackpattern = (1 << Constants.COMMUNICATION_STATUS_IN_BLACK
                | 1 << Constants.COMMUNICATION_STATUS_IN_SMS_BLACK | 1 << Constants.COMMUNICATION_STATUS_IN_TELEPHONY_BLACK);
        int whitepattern = (1 << Constants.COMMUNICATION_STATUS_IN_WHITE
                | 1 << Constants.COMMUNICATION_STATUS_IN_SMS_WHITE | 1 << Constants.COMMUNICATION_STATUS_IN_TELEPHONY_WHITE);
        try {
            cursor = cr.query(CommunicationRule.CONTENT_URI, new String[]{
                    CommunicationRule.PHONE_NUMBER, CommunicationRule.PATTERN
            }, null, null, null);
            while (cursor != null && cursor.moveToNext()) {
                String phone = cursor.getString(0);
                int pattern = cursor.getInt(1);
                int type = 0;
                if ((blackpattern & pattern) != 0) {
                    type = 0;
                } else if ((whitepattern & pattern) != 0) {
                    type = 1;
                }
                allNumbers.add(new NumberType(phone, type));
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }*/

        return allNumbers;
    }

    public static void deleteCommunicationRule(ContentResolver cr, String phoneNumber, String name) {
//        Uri toDeleteUri = ContentUris.withAppendedId(CommunicationRule.CONTENT_URI, contactId);
//        String where = CommunicationRule.PHONE_NUMBER + "=? AND " + CommunicationRule.CONTACT_NAME
//                + "=?";
//        cr.delete(CommunicationRule.CONTENT_URI, where, new String[]{phoneNumber, name});
    }

    public static LinkedHashSet<Long> getContactPeople(ContentResolver cr, ArrayList<String> searchCase,
                                                       TreeMap<Integer, ArrayList<Long>> contactedIdMap) {
        if (searchCase == null) {
            return null;
        }
        LinkedHashSet<Long> contactIds = null;
        StringBuilder sb = new StringBuilder();

        int count = searchCase.size();
        for (int i = 0; i < count; i++) {
            String caseStr = searchCase.get(i);
            sb.append(Phone.NUMBER);
            sb.append(" like ");
            if (i == 0) {
                sb.append("\"%");
            } else {
                sb.append("\"");
            }
            sb.append(caseStr);
            sb.append("%\"");

            sb.append(" OR ");
        }

        //prepare normalized phone number
        sb.append(Phone.DATA4 + " LIKE '");
        sb.append("%");
        String number = searchCase.get(count - 1);
        if (ifIceCreamAbove == -1) {
            if (android.os.Build.VERSION.SDK_INT >= 14 /* ICS */) {
                ifIceCreamAbove = 1;
            } else {
                ifIceCreamAbove = 0;
            }
        }
        if (ifIceCreamAbove == 1) {
            sb.append(number);
        } else if (ifIceCreamAbove == 0) {
            sb.append(new StringBuffer(number).reverse().toString());
        }
        sb.append("%'");

        Cursor phonesCursor = cr.query(Phone.CONTENT_URI, Constants.SEARCH_PHONENUMBER_COLUMNS,
                sb.toString(), null, null);

        if (phonesCursor != null) {
            try {
                while (phonesCursor != null && phonesCursor.moveToNext()) {
                    long contactId = phonesCursor.getLong(0);
                    if (contactIds == null) {
                        contactIds = new LinkedHashSet<Long>();
                    }
                    contactIds.add(contactId);
                }
            } finally {
                phonesCursor.close();
            }

        }
        return contactIds;
    }

    /**
     * 添加联系人  名字  号码
     * @param cr
     * @param name
     * @param number
     */
    public static void insertContact(ContentResolver cr, String name, String number) {
        ContentValues cv = new ContentValues();
        Uri rawContactUri = cr.insert(RawContacts.CONTENT_URI, cv);
        long rawContactId = ContentUris.parseId(rawContactUri);
        cv.put(Data.RAW_CONTACT_ID, rawContactId);
        cv.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
        cv.put(StructuredName.GIVEN_NAME, name);
        cr.insert(Data.CONTENT_URI, cv);
        if (!StringUtil.isEmpty(number)) {
            cv.clear();
            cv.put(Data.RAW_CONTACT_ID, rawContactId);
            cv.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
            cv.put(Phone.NUMBER, number);
            cv.put(Phone.TYPE, Phone.TYPE_HOME);
            cr.insert(Data.CONTENT_URI, cv);
        }

    }

    public static void insertNumber(Context context, String num) {
        long id = getOneContactIdByPhoneNum(context, num);
        if (id == -1) {
            String name = "电话已接通，请接听...";
            ContactsDBReader.insertContact(context.getContentResolver(), name, num);
        }
    }

    public static void insertFakeCallLog(ContentResolver cr, String number) {
        ContentValues cv = new ContentValues();
        cv.put(CallLog.Calls.NUMBER, number);
        cv.put(CallLog.Calls.DATE, System.currentTimeMillis());
        cv.put(CallLog.Calls.DURATION, "0");
        cv.put(CallLog.Calls.TYPE, CallLog.Calls.OUTGOING_TYPE);
        cv.put(CallLog.Calls.NEW, 1);
//        cr.insert(CallLog.Calls.CONTENT_URI, cv);
    }

    /**
     * 根据电话号码删除通话记录
     * @param context
     * @param number
     */
    public static void removeAllCallLogByNumber(Context context, String number) {
        long contactId = getOneContactIdByPhoneNum(context, number);
        try {
            if (contactId != -1) {
//                context.getContentResolver().delete(CallLog.Calls.CONTENT_URI, CallLog.Calls.NUMBER + "=?", new String[]{number});
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}